<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
/*
    var fn;
    function foo() {
        var a = 2;
        function baz() { 
            console.log( a );
        }
        fn = baz; 
    }
    function bar() {
        fn(); 
    }

    foo();
    bar(); // 2
*/

// 自执行创建模块
(function(window) {
    // states 结构预览
    // states = {
    //     a: 1,
    //     b: 2,
    //     m: 30,  
    //     o: {}
    // }
    var states = {};  // 私有变量，用来存储状态与数据

    // 判断数据类型
    function type(elem) {
        if(elem == null) {
            return elem + '';
        }
        console.log(toString.call(elem).replace(/[\[\]]/g, '').split(' ')[1].toLowerCase())
        return toString.call(elem).replace(/[\[\]]/g, '').split(' ')[1].toLowerCase();
    }


    /**
     * @Param name 属性名
     * @Description 通过属性名获取保存在states中的值
    */
    function get(name) {
        return states[name] ? states[name] : '';
    }

    function getStates() {
        return states;
    }

    /*
    * @param options {object} 键值对
    * @param target {object} 属性值为对象的属性，只在函数实现时递归中传入
    * @desc 通过传入键值对的方式修改state树，使用方式与小程序的data或者react中的setStates类似
    */
    function set(options, target) {
        var keys = Object.keys(options);
        var o = target ? target : states;
        console.log(states)

        keys.map(function(item) {
            if(typeof o[item] == 'undefined') {
                o[item] = options[item];
            } else {
                type(o[item]) == 'object' ? set(options[item], o[item]) : o[item] = options[item];
            }
            return item;
        })
    }

    // 对外提供接口
    window.get = get;
    window.set = set;
    window.getStates = getStates;
})(window)

// 具体使用如下

set({ a: 20 });     // 保存 属性a
set({a:40.366})
// set({ b: 100 });    // 保存属性b
// set({ c: 10 });     // 保存属性c

// 保存属性o, 它的值为一个对象
// set({ 
//     o: {
//         m: 10,
//         n: 20
//     }
// })

// 修改对象o 的m值
// set({
//     o: {
//         m: 1000
//     }
// })

// 给对象o中增加一个c属性
// set({
//     o: {
//         c: 100
//     }
// })
console.log(getStates())
</script>
</body>
</html>